﻿using huqiang.Core.HGUI;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.Experimental.Rendering.Universal;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;

public class UIRenderPass : RenderObjectsPass
{
    Camera cam;
    static string[] blockNames = new string[] { "_MainTex", "_t1", "_t2", "_t3", "_t4", "_t5", "_t6", "_t7" };
    static MaterialPropertyBlock propertyBlock;
    static Material UIMat;
    List<HGUIRender> renders;
    
    public UIRenderPass(string profilerTag, RenderPassEvent renderPassEvent, string[] shaderTags, RenderQueueType renderQueueType, int layerMask, RenderObjects.CustomCameraSettings cameraSettings) : base(profilerTag, renderPassEvent, shaderTags, renderQueueType, layerMask, cameraSettings)
    {
    }
    public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor)
    {
        if (renders == null)
            renders = new List<HGUIRender>();
        else renders.Clear();
        HGUIRender.GetContextRender(cam,renders);
        for (int i = 0; i < renders.Count; i++)
        {
            ConfigureDrawCmd2(cmd, renders[i]);
        }
#if UNITY_EDITOR
        if(cam.cameraType==CameraType.SceneView)
        {
            HGUIRender[] all =  UnityEditor.SceneAsset.FindObjectsOfType<HGUIRender>();
            for (int i = 0; i < all.Length; i++)
            {
                ConfigureDrawCmd2(cmd, all[i]);
            }
        }
#endif
    }
    void ConfigureDrawCmd(CommandBuffer cmd, HGUIRender render)
    {
        if (!render.gameObject.activeInHierarchy)
            return;
        render.ApplyToCamera();
        if (UIMat == null)
            UIMat = new Material(Shader.Find("HGUI/UIDef"));
        Matrix4x4 matrix = new Matrix4x4();
        var trans = render.transform;
        if (render.renderMode == RenderMode.WorldSpace)
            matrix.SetTRS(trans.position, trans.rotation, trans.lossyScale);
        else matrix.SetTRS(render.renderPos, render.renderRotation, render.renderScale);
#if UNITY_EDITOR
        if(cam.cameraType==CameraType.SceneView)
            matrix.SetTRS(trans.position, trans.rotation, trans.lossyScale);
#endif
        var mesh = render.mesh;
        var materials = render.materials;
        int max = mesh.subMeshCount;
        if (max > materials.Count)
            max = materials.Count;
        
        int queue = render.renderQueue;
        UIMat.renderQueue = queue;
        if (render.renderMode == RenderMode.ScreenSpaceOverlay)
        {
            UIMat.SetFloat("_ZWrite", 0);
            UIMat.SetFloat("_ZTest", 6);
        }
        else if (render.renderMode == RenderMode.ScreenSpaceCamera)
        {
            UIMat.SetFloat("_ZWrite", 0);
            UIMat.SetFloat("_ZTest", 2);
        }
        else
        {
            UIMat.SetFloat("_ZWrite", 1);
            UIMat.SetFloat("_ZTest", 2);
        }
        if (propertyBlock == null)
            propertyBlock = new MaterialPropertyBlock();
        for (int i = 0; i < max; i++)
        {
            var mat = materials[i];
            if (mat == null)
            {
                var m = UIMat;//GetNextMat();
                propertyBlock.Clear();
                int s = i * 8;
                for (int j = 0; j < 8; j++)
                {
                    if (render.textures[s] != null)
                    { 
                        propertyBlock.SetTexture(blockNames[j], render.textures[s]);
                    }
                    s++;
                }
                cmd.DrawMesh(mesh, matrix, m, i, 0, propertyBlock);
            }
            else
            {
                materials[i].renderQueue = queue;
                cmd.DrawMesh(mesh, matrix, materials[i], i, 0);
            }
            queue++;
        }
    }
    public void Setup(ref RenderingData renderingData)
    {
        cam = renderingData.cameraData.camera;
#if UNITY_EDITOR
        if (!Application.isPlaying)
        {
            HGUIRender[] all = UnityEditor.SceneAsset.FindObjectsOfType<HGUIRender>();
            for (int i = 0; i < all.Length; i++)
            {
                all[i].Setup();
            }
        }
#endif
    }
    public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
    {
        //Debug.Log(new UIMesh().alltris.Length);
    }
    void ConfigureDrawCmd2(CommandBuffer cmd, HGUIRender render)
    {
        if (!render.gameObject.activeInHierarchy)
            return;
        render.ApplyToCamera();
        if (UIMat == null)
            UIMat = new Material(Shader.Find("HGUI/UIDef"));
        Matrix4x4 matrix = new Matrix4x4();
        var trans = render.transform;
        if (render.renderMode == RenderMode.WorldSpace)
            matrix.SetTRS(trans.position, trans.rotation, trans.lossyScale);
        else matrix.SetTRS(render.renderPos, render.renderRotation, render.renderScale);
#if UNITY_EDITOR
        if (cam.cameraType == CameraType.SceneView)
            matrix.SetTRS(trans.position, trans.rotation, trans.lossyScale);
#endif

        int queue = render.renderQueue;
        UIMat.renderQueue = queue;
        if (render.renderMode == RenderMode.ScreenSpaceOverlay)
        {
            UIMat.SetFloat("_ZWrite", 0);
            UIMat.SetFloat("_ZTest", 6);
        }
        else if (render.renderMode == RenderMode.ScreenSpaceCamera)
        {
            UIMat.SetFloat("_ZWrite", 0);
            UIMat.SetFloat("_ZTest", 2);
        }
        else
        {
            UIMat.SetFloat("_ZWrite", 1);
            UIMat.SetFloat("_ZTest", 2);
        }
        if (propertyBlock == null)
            propertyBlock = new MaterialPropertyBlock();

        var batchs = render.batchs;
        if (batchs != null)
        {
            var bats = batchs.batches;
            for (int i = 0; i < batchs.top; i++)
            {
                var bat = bats[i];
                bat.Apply();
                propertyBlock.Clear();
                int s = i * 8;
                for (int j = 0; j < 8; j++)
                {
                    var tex = bat.MatBlock.textures[j];
                    if (tex != null)
                        propertyBlock.SetTexture(blockNames[j], tex);
                }
                cmd.DrawMesh(bat.mesh, matrix, UIMat, 0, 0, propertyBlock);
            }
        }

        //for (int i = 0; i < max; i++)
        //{
        //    var mat = materials[i];
        //    if (mat == null)
        //    {
        //        var m = UIMat;//GetNextMat();
        //        propertyBlock.Clear();
        //        int s = i * 8;
        //        for (int j = 0; j < 8; j++)
        //        {
        //            if (render.textures[s] != null)
        //            {
        //                propertyBlock.SetTexture(blockNames[j], render.textures[s]);
        //            }
        //            s++;
        //        }
        //        cmd.DrawMesh(mesh, matrix, m, i, 0, propertyBlock);
        //    }
        //    else
        //    {
        //        materials[i].renderQueue = queue;
        //        cmd.DrawMesh(mesh, matrix, materials[i], i, 0);
        //    }
        //    queue++;
        //}
    }
}
